初心者でもわかるコンテナ / Docker / ECS 話 #devio2021
こんにちはクラスメソッドのスジェです。
今回、devio 2021 decadeでECSに関する内容で登壇するので、その内容をブログでまとめてみようと思います。
ECSというサービスがあることも分かっているし、たくさん使っていることも分かっているけど、どんなサービスなのか? なぜ使うのか?コンテナは何か? などコンテナについてよく知らない初心者でも理解できるように、コンテナとDocker、ECSについてご説明したいと思います。
始まり
Amazon Elastic Container Service (Amazon ECS) は完全マネージド型コンテナオーケストレーションサービスであり、コンテナ化されたアプリケーションを簡単にデプロイ、管理、スケールするのに役立ちます。- AWS ECS 公式ページ紹介文
コンテナについてよく知らない初心者に「コンテナ化されたアプリケーション」、「コンテナオーケストレーションサービス」という言葉はすぐには理解できません。
この紹介文をもとに一つ一つ見ていきましょう。
コンテナについて
コンテナ化?
コンテナを使用すると、アプリケーションのコード、構成、依存関係を単一のオブジェクトにパッケージ化できます。サーバーにインストールされたオペレーティングシステムを共有し、リソースが分離したプロセスとして実行され、環境に関係なく、迅速で信頼性も高く、一貫性のあるデプロイを保証しています。 - AWS カテゴリ別のサービス学習[コンテナ]
AWSの説明のようにアプリケーションに必要な部分をパッケージングし、アプリケーションごとに隔離する方式です。
コンテナが登場する前は、今も多く使われている仮想機械(VM)を基盤に隔離された環境を構築しました。
VMは次のような環境で構成されます。
VMを利用して多様なアプリケーションの配布は可能でした。
しかし、次のような明確な限界があったため、使用に限界がありました。
- マシンレベルの分離のためにハードウェア仮想化が必要
- 様々な部分の仮想化が必要であるため、多くのリソースとオーバーヘッドが伴う
- OSのイメージも含むため、VMイメージのサイズが大きい
- サーバーの一貫的な運用が難しい(snowflake server)
その後、Linuxでcgroup(controlgroups)というLinuxカーネルの機能が作られ、ネームスペース(namespace)とともに使用されるようになります。
この機能によって、ネームスペース内のプロセスに対して独立的なリソースを保障することができるようになり、ネームスペースが隔離された空間のように作動できるようになります。
これがリナックスコンテナ(Linux Container, LXC)の基盤となります。
そして、Linuxコンテナを基盤に、今日、我々がコンテナといえば、真っ先に思い浮かぶdockerが開発されます。1
もちろん、Linuxコンテナとdockerが完全に同一の技術ではなく、この文で調べるコンテナの概念はdockerに近いです。
コンテナは以下のような環境で構成されています。
このようにコンテナごとに隔離して管理することをコンテナ化といいます。
コンテナを使う理由
下記のようなコンテナの特徴によって、コンテナを使うようになりました。
- ハードウェアの仮想化を行わずにカーネルだけを共有する。
- ハードウェアのエミュレーションがないため、速いスピードで実行される。
- イメージのサイズがVMに比べてはるかに小さい
- コンテナ間に影響を与えず、dockerのようにイメージ基盤でコンテナを実行する場合、特定の実行環境を簡単に再利用することができる。
- 実行・パッチ・アップデートなど維持管理に関してオーバーヘッドが減少する
- サービスが細分化されているマイクロサービスアーキテクチャ(MSA)の特性にコンテナのサービス別隔離や拡張性などを上手く活用できる
- ただし、最初にイメージを定義したOSでのみ使用できる。
(リナックスならリナックスでのみ、ウィンドウならウィンドウでのみ可能)
つまり、「アプリケーションの展開·管理を簡単にしてくれるし、オーバーヘッドも少ない」という特徴があるのです。
Docker
上記のメリットがありましたが、コンテナはあまり注目されませんでした。
その後、docker(ドッカー) 2の公開後、コンテナに対する関心が高まり始めました。
そしてドッカーは
- 短くなるビルド・展開周期
- マイクロサービスで設計されたアプリケーションが増え、管理単位の縮小が必要
- クラウドサービスの発展
という時代の流れとイメージの階層化やユニオンファイルシステム 3などの特徴をもとにコンテナ技術といえば、多くの人がdockerを思い浮かべるほど発展するようになります。
dockerの動作方式
dockerは、アプリケーションを実行するためのファイル集をイメージということで管理します。
このようなイメージをローカルあるいはdocker hubなどのようなリモートリポジトリにタグを付けてコミットします。
このタグでイメージのバージョンを区分します。
そして、コミットしたイメージを利用してコンテナを作成します。作成したコンテナは、ポートフォワーディングでアクセスできます。
イメージのコミットからコンテナの作成は、次のような手順となります。
- コミットするイメージ(コンテナの環境)構成
- 作成したイメージをレジストリにコミット
- コミットしたイメージでコンテナを作成
つまりイメージ作成、イメージ保存、コンテナ作成の順に動作します。
環境構築、つまりイメージの構成には様々なパッケージのダウンロードや環境設定などが必要です。
しかし一つ一つ直接に作業するのはとても非効率的です。
これを解決するために、コミットするイメージの内容(環境構築の内容)をdockerfileというファイルに作成することができます。
基礎的なコマンドを含むdockerfileの簡単な例を以下の通りです。
FROM ubuntu:20.04 \ RUN apt-get update && apt-get install apache2 -y \ WORKDIR /var/www/html \ RUN ["/bin/bash", "-c", "echo >> test.html"] \ EXPOSE 80 \ ENV APACHE_RUN_USER www-data \ ENV APACHE_RUN_GROUP www-data \ ENV APACHE_LOG_DIR /var/log/apache2 \ CMD apachectl -DFOREGROUND
このようにdockerfileを利用することは、環境構築、イメージコミット、gitなどの開発ツールを通じてビルドおよび配布を自動化できるというメリットがあります。
コンテナの作成と展開
dockerがどのように動くのかを軽くにみました。
しかし、あるサービスを構成するためには、いくつかのアプリケーションやデータベースなどが結合して完成されます。
それで作成の順序(じゅんじょ)を気にしながら、オプションが違う多くのコマンドを実行する必要がありますが、これを手でするのは非効率的です。
dockerではこのためにdocker composeというツールを提供しています。
docker composeを利用すると、長いコマンドを1つのyamlファイルとして定義するので、環境を把握しやすくなります。
また、コンテナの実行順序やディペンデンシーなども解決できます。
内容の例は以下の通りです。
version: "3.9" # optional since v1.27.0 services: web: build: . ports: - "5000:5000" volumes: - .:/code - logvolume01:/var/log links: - redis redis: image: redis volumes: logvolume01: {}
こうして1つのサーバー(ホスト)に複数のコンテナを展開する方法をみました。しかし、さらにコンテナが必要となる場合にはサーバーを追加(サーバークラスタリング)する必要があります。
それでは、サーバー間のコンテナの管理はどのようにすべきでしょうか?
このために、さまざまなサーバーのコンテナを管理するコンテナオーケストレーション(container orchestration)という概念が必要になり、このような機能をするものをコンテナオーケストレーションツール(container orchestration tool)と言います。
現在多く使用されているのはkubernates、Docker Swarm、Apache Mesos、AWS ECS などがあります。
オーケストレーションツールは、次のような機能を提供しています。
- サーバーの特性やリソース、展開状態を把握し、コンテナを割り当てるスケジューリング
- サーバーでドッカーを通じて指定されたコンテナを安全に実行
- アップグレード、ロールバックなどサービスの展開に関する対応
- エラーなどの対応
- 新しいサーバーやコンテナが追加された時に発見するサービスディスカバリー(service discovery)、サーバー間のネットワーキングなどのクラスターリソース作成
このようにただ展開するだけで終わりではなく、サービスディスカバリー、配布方式、ロードバランシング、ロギング及びモニタリング、高可用性など多くの部分を考慮しなければなりません。
AWS ECS
最初に話しました「コンテナ化」、「コンテナオーケストレーションサービス」についての説明が終わりましたので、最後にECSを見てみましょう。
ECS とは?
上記で説明したようにECS(Elastic Container Service)は、AWSから提供しているコンテナオーケストレーションサービスです。
ECS を使用してAmazon EC2 インスタンスの管理型クラスター、あるいはAWS Fargateによるサーバレス環境でアプリケーションを実行できます。
ECSを使用することによって、次のようなメリットが得られます。
- 多様なAWSのサービス連携
AWSで提供している多様なサービスとオプションを連携して、より効率的にコンテナを管理することができます。 - コントロールプレーンやノードを管理する必要がない
AWS Fargateを通じてサーバレス環境を利用でき、コントロールプレーンまたはノードの管理、インスタンスパッチおよび調整が不要なため、運営に必要な時間が削減されます。 - コンピューティングコストが削減
クラウドサービスで、物理的サーバーに対する料金を節約することができます。 また、ECSはプロビジョニングや自動調整を自律的に処理するため、コンピューティングコストを最大50%まで削減することができます。 - セキュリティ要件や規制要件を満たしている
Amazon ECS はネイティブで AWS マネジメントとガバナンスソリューションが統合されているため、実質、全世界の規制当局が定める安全性やコンプライアンスのスタンダードを満たすことができます。
AWSが提供しているサービスなので、ちゃんと活用するためにはAWSの他のサービスについてある程度の知識が必要です。
関連サービス
作動方法を説明する前に関連サービスを簡単に見てみましょう。
- AWS ECR(Elastic Container Registry)
- コンテナイメージのリポジトリです。
- AWS Fargate
- 従量制サーバーレスコンピューティングエンジンです。 ECS·EKSとの両方で動作します。
- AWS ELB(Elastic Load Balancer)
- ロードバランサーです。 ALBと一緒に使用して動的ポートを指定できます。
- AWS VPC
- ECSに必要なネットワークリソースを提供するサービスです。
- AWS IAM
- クラスターやサービスなど、様々な作業の権限を設定するサービスです。
- AWS CloudWatch
- コンテナのメトリクスとログなどが確認できるサービスです。 コンテナ型アプリケーション及びマイクロサービスに対するモニタリング、トラブルシューティング及びアラームのためのサービスであるContainer Insightも提供しています。
他にも、クバネチスのためのEKS、コミット・ビルド・展開に関するAWS Codeシリーズなど、様々なサービスと連携が可能です。
ECSの動作方式
ECSの構成要素は大きく分けて5つです。
- Task Definition(タスク定義)
- Task(タスク)
- Continer Instacne(コンテナインスタンス)
- Service(サービス)
- Cluster(クラスター)
これを図式化すると次のようになります。
- Task
ECSの最小単位は、taskです。
そして1個以上のコンテナがtaskに構成されます。 - Task Definition
taskの構成要素は、taskdefinitionにjson形式で作成されています。
作成された内容を参考に、task が構成されます。
task definitionで作業およびコンテナが参考にするイメージ、使用するリソース量、起動タイプ、ロギング構成など様々なパラメータを定義することができます。 - Service
task definitionを参考にしてtaskを実行します。また、希望する数のtaskを維持・管理するスケジューラーの役割をします。
選択的にロードバランサーの後ろから実行することで、ロードバランシングとオートスケーリング機能が行えます。 - Container Instance
ECSコンテナエージェントを実行し、clusterに登録されたEC2インスタンスです。
Linux、WindowsOSに対応しており、オンプレミスVMなどの他のOSにも対応しています。
Fargate起動タイプを使用するtaskは、サーバレスとして展開されるのでcontainer instanceは適用されません。 - Cluster container instance(Fargateなら、task)の論理的グループです。
それで次のような手順で作業を行うことになります。
- コンテナのイメージを保存所(ECR)にコメット
- task definitionで使用するイメージやスタート(起動)タイプ、リソース定義
- cluster作成
- serviceがtask definitionを参考にしてtask作成
- elbに入ってきたリクエストによってオートスケーリング及びロードバランシング開始
他には
ECR/ECSとAWS code シリーズとともに活用して、コードのコミットから展開まで自動化したり
ECSのtaskのための様々なオプション(AWS Wavelength, AWS Outposts)などと共に使用すると、より効率的で能動的なコンテナ生態系を構築することができます。
devio 2021 decade
今回の発表のためにコンテナからECSまで整理し、私も再び概念を固めることができました。
この他にもdevio 2021 decadeに多様なセッションが用意されていますのご興味のある方は参考してください。
お読みいただきありがとうございました。
タイポ・内容のフィードバックなどはmust01940 gmailでいただければ幸いです。
参考資料
-
現在のdockerはLinuxコンテナとの従属関係から離れ、containerdとruncを基盤に動作します。
もはやこの二つは「システムコンテナ(Linuxコンテナ)か? アプリケーションコンテナ(Docker)か?」に区分されます。 ↩ -
オープンソースのコミュニティプロジェクト、オープンソースプロジェクトのツール、プロジェクトの主要支持者である会社、以前に会社で支援したツールすべてが "Docker" です。
本記事で説明する"Docker"は、コンテナを実行·管理するApplication Container Runtimeです。 ↩ -
イメージには、アプリケーションの実行に必要な様々なファイルが階層化されていて、これをレイヤー(Layer)といいます。
複数のレイヤーを1つのファイルシステムのように管理することをユニオンファイルシステム(Union File System)といいます。
ひとつのファイルシステムに複数のファイルシステムをマウントすると、重複するファイルがあります。
ユニオンファイルシステムは、このようなファイルを最後に作成されるファイルで上書きする方法で管理しています。 ↩